﻿#pragma once

#include "MonsterObject.h"
#include "../MirDatabase/CharacterInfo.h"
#include "../../Shared/Enums.h"
#include "../../Shared/Data/IntelligentCreatureData.h"
#include "MapObject.h"
#include "../Settings.h"
#include "../MirDatabase/MonsterInfo.h"
#include "PlayerObject.h"
#include "../../Shared/Packet.h"
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include "exceptionhelper.h"
#include "../../stringhelper.h"

using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
namespace S = ServerPackets;

namespace Server::MirObjects
{
    class IntelligentCreatureObject : public MonsterObject
    {
    public:
        bool Summoned = false;
        virtual ~IntelligentCreatureObject()
        {
            delete CreatureInfo;
            delete CreatureRules;
        }

        std::string getCustomName() const;
        void setCustomName(const std::string &value);

        UserIntelligentCreature *CreatureInfo;

        IntelligentCreatureType PetType = IntelligentCreatureType::None;

        ItemGrade GradeFilter = ItemGrade::None;

        IntelligentCreatureRules *CreatureRules = new IntelligentCreatureRules();
        IntelligentCreatureItemFilter *getItemFilter() const;
        void setItemFilter(IntelligentCreatureItemFilter *value);

        IntelligentCreaturePickupMode getCurrentPickupMode() const;
        void setCurrentPickupMode(IntelligentCreaturePickupMode value);

        std::vector<MapObject*> TargetList;
        bool FillingTargetList = false;
        bool DoTargetList = false;
        bool TargetListTargetClean = false;

        int getFullness() const;
        void setFullness(int value);
        long long FullnessTicker = 0;
        static constexpr long long FullnessDelay = Settings::Second;

        bool DoDelayedPickup = false;
        long long DelayedpickupTicker = 0;
        static constexpr long long DelayedpickupDelay = Settings::Second; //1 second

        long long CreatureTime = 0;

        long long getBlackstoneTime() const;
        void setBlackstoneTime(long long value);
        static constexpr long long BlackstoneProduceTime = 10800; //3 hours in seconds

        long long PearlTicker = 0;
        static constexpr long long PearlProduceCount = 1000; //1000 items = 1 pearl

        long long AnimvariantTicker = 0;
        static constexpr long long AnimvariantDelay = 10 * Settings::Second; //10 seconds

        long long getMaintainfoodTime() const;
        void setMaintainfoodTime(long long value);

        long long TimedSayTicker = 0;
        static constexpr long long TimedSayDelay = 20 * Settings::Second;

    private:
        bool shortcheck = true;

    public:
        bool getBlocking() const override;

    protected:
        bool getCanMove() const override;

    public:
        std::string getName() const override;
        void setName(const std::string &value) override;
    protected:
        bool getCanAttack() const override;

    public:
        ObjectType getRace() const override;


    protected:
        IntelligentCreatureObject(MonsterInfo *info);

    public:
        void SetOperateTime() override;

        void Process() override;

        void ProcessAnimVariant();

        void ProcessBuffs();

    protected:
        void ProcessAI() override;

        void ProcessSearch() override;
        void ProcessRoam() override;

        void ProcessTarget() override;

        void FindTarget() override;

    private:
        void FindItemTarget();

        bool FillTargetList(Point *location);

        void ProcessTargetList();

        bool CheckAndMoveTo(Point *location);

    protected:
        void Attack() override;

        bool DelayedAttack(long long delay);

    public:
        void DelayedPickup(long long delay);

        void PickupAllItems(Point *location);

        void PickUpItem(Point *location);

    private:
        bool CheckItemAgainstFilter(ItemType iType);

    public:
        void ManualPickup(bool mousemode, Point *atLocation);

        void IncreaseFullness(int amount);

        void DecreaseFullness(int amount);

        void IncreasePearlProduction();

        void ProcessBlackStoneProduction();

        void ProcessMaintainFoodBuff();

        void CreatureTimedSay(const std::string &message);

        void CreatureSay(const std::string &message);

        void ReceiveChat(const std::string &text, ChatType type) override;

        bool IsAttackTarget(PlayerObject *attacker) override;
        bool IsAttackTarget(MonsterObject *attacker) override;
        bool IsFriendlyTarget(PlayerObject *ally) override;
        bool IsFriendlyTarget(MonsterObject *ally) override;
        int Attacked(PlayerObject *attacker, int damage, DefenceType type = DefenceType::ACAgility, bool damageWeapon = true) override;
        int Attacked(MonsterObject *attacker, int damage, DefenceType type = DefenceType::ACAgility) override;

        int Struck(int damage, DefenceType type = DefenceType::ACAgility) override;

        void ApplyPoison(Poison *p, MapObject *Caster = nullptr, bool NoResist = false, bool ignoreDefence = true) override;

    private:
        bool IsMasterGroupMember(MapObject *player);


    public:
        void Spawned() override;

        void Die() override;

        Packet *GetInfo() override;
    };
}
